﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NTmdb.Net;

namespace NTmdb.TestProject
{
    /// <summary>
    ///     This is a test class for ApiWrapperOnlineTest and is intended
    ///     to contain all ApiWrapperOnlineTest Unit Tests
    /// </summary>
    /// <remarks>
    ///     NOTE: This test class tests does not test much more than whether or not errors are thrown.
    ///     There are more detailed unit tests, in other test classes.
    /// </remarks>
    [TestClass]
    public class ApiWrapperOnlineTest
    {
        #region Properties

        /// <summary>
        ///     Your TMDb API key.
        /// </summary>
        private const String ApiKey = "ba9a4d5a02b4438300a712d31316a3ff";

        /// <summary>
        ///     The TMDb session ID of your account.
        /// </summary>
        private const String SessionId = "8958bf504776aa49f670af8b22c18a26ee05a580";

        /// <summary>
        ///     The ID of your TMDb account.
        /// </summary>
        private const Int32 AccountId = 5976610;

        /// <summary>
        ///     Gets or sets a instance of the test target.
        /// </summary>
        /// <value>A instance of the test target.</value>
        private static ApiWrapper Target { get; set; }

        #endregion Properties

        /// <summary>
        ///     Creates a new instance of the API Wrapper.
        /// </summary>
        /// <param name="testContext"></param>
        [ClassInitialize]
        public static void MyClassInitialize( TestContext testContext )
        {
            Target = new ApiWrapper
                {
                    ApiClient = new ApiClientNet()
                };
            var config = new ApiConfiguration();
            config.RestoreDefaultValues( ApiKey );
            Target.ApiConfiguration = config;
        }

        /// <summary>
        ///     Generic check for all TMDb results.
        /// </summary>
        /// <typeparam name="T">The type of the result.</typeparam>
        /// <param name="result">The result.</param>
        private void CheckGenericResult<T>( ITmdbResult<T> result, Boolean checkETag = true )
        {
            Assert.IsNull( result.Error );
            Assert.IsNotNull( result.Result );
            if ( result.Result is ITmdbModelBase && checkETag )
                Assert.IsFalse( String.IsNullOrEmpty( ( result.Result as ITmdbModelBase ).ETag ), "ETag is empty or null" );
        }

        /// <summary>
        ///     A test for ApiWrapper Constructor
        /// </summary>
        [TestMethod]
        public void ApiWrapperConstructorTest()
        {
            var target = new ApiWrapper();
            Assert.IsNotNull( target ); //Just that the method contains a assert....
        }

        #region Configuration

        /// <summary>
        ///     A test for GetConfigurationAsync
        /// </summary>
        [TestMethod]
        public async Task GetConfigurationAsyncTest()
        {
            var actual = await Target.GetConfigurationAsync();
            CheckGenericResult( actual );

            var config = actual.Result;
            Assert.IsTrue( config.ChangeKeys.Any() );
            Assert.IsFalse( String.IsNullOrEmpty( config.ImageConfiguration.BaseUrl ) );
            Assert.IsFalse( String.IsNullOrEmpty( config.ImageConfiguration.SecureBaseUrl ) );
            Assert.IsTrue( config.ImageConfiguration.PosterSizes.Any() );
            Assert.IsTrue( config.ImageConfiguration.BackdropSizes.Any() );
            Assert.IsTrue( config.ImageConfiguration.ProfileSizes.Any() );
            Assert.IsTrue( config.ImageConfiguration.LogoSizes.Any() );
        }

        #endregion Configuration

        #region Authentication

        /// <summary>
        ///     A test for GetAuthenticationTokenAsync
        /// </summary>
        [TestMethod]
        public async Task GetAuthenticationTokenAsyncTest()
        {
            var actual = await Target.GetAuthenticationTokenAsync();
            CheckGenericResult( actual );

            var token = actual.Result;
            Assert.IsFalse( String.IsNullOrEmpty( token.ExpiresAtString ) );
            Assert.IsFalse( String.IsNullOrEmpty( token.Token ) );
            Assert.IsTrue( token.Success );

            var expireDate = token.GetExpireDate( Target.ApiConfiguration.JsonDateTimePattern );
            Assert.IsTrue( expireDate.HasValue );

            var isEpired = token.GetIsExpired( Target.ApiConfiguration.JsonDateTimePattern );
            Assert.IsTrue( isEpired.HasValue );
            Assert.IsFalse( isEpired.Value );
        }

        /// <summary>
        ///     A test for GetSessionAsync
        /// </summary>
        [TestMethod]
        public async Task GetSessionAsyncTest401()
        {
            var token = await Target.GetAuthenticationTokenAsync();
            Assert.IsTrue( token.Result.Success, "GetAuthenticationTokenAsync failed!" );

            var actual = await Target.GetSessionAsync( token.Result.Token );
            Assert.IsTrue( actual.Error.Message.Contains( "401" ) );
        }

        /// <summary>
        ///     A test for GetSessionAsync
        /// </summary>
        //[TestMethod]
        public async Task GetSessionAsyncTest()
        {
            var token = await Target.GetAuthenticationTokenAsync();
            Assert.IsTrue( token.Result.Success, "GetAuthenticationTokenAsync failed!" );

            //Before you can get a valid session ID, you must accept the authentication token on the TMDb site.
            var urlToOpen = String.Format( "https://www.themoviedb.org/authenticate/{0}", token.Result.Token );
            Process.Start( urlToOpen );

            var actual = await Target.GetSessionAsync( token.Result.Token );
            CheckGenericResult( actual );

            var session = actual.Result;
            Assert.IsFalse( String.IsNullOrEmpty( session.SessionId ) );
            Assert.IsTrue( session.Success );
        }

        /// <summary>
        ///     A test for GetGuestSessionAsync
        /// </summary>
        [TestMethod]
        public async Task GetGuestSessionAsyncTest()
        {
            var actual = await Target.GetGuestSessionAsync();
            CheckGenericResult( actual );

            var session = actual.Result;
            Assert.IsFalse( String.IsNullOrEmpty( session.ExpiresAtString ) );
            Assert.IsFalse( String.IsNullOrEmpty( session.GuestSessionId ) );
            Assert.IsTrue( session.Success );

            var expireDate = session.GetExpireDate( Target.ApiConfiguration.JsonDateTimePattern );
            Assert.IsTrue( expireDate.HasValue );
            Assert.IsTrue( expireDate.Value.Ticks > DateTime.Now.Ticks );

            var isEpired = session.GetIsExpired( Target.ApiConfiguration.JsonDateTimePattern );
            Assert.IsTrue( isEpired.HasValue );
            Assert.IsFalse( isEpired.Value );
        }

        #endregion Authentication

        #region Account

        /// <summary>
        ///     A test for GetAccountAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountAsyncTest()
        {
            var actual = await Target.GetAccountAsync( SessionId );
            CheckGenericResult( actual );

            var account = actual.Result;
            Assert.IsTrue( account.Id > 0 );
            Assert.IsFalse( String.IsNullOrEmpty( account.Iso3166_1 ) );
            Assert.IsFalse( String.IsNullOrEmpty( account.Iso639_1 ) );
            Assert.IsFalse( String.IsNullOrEmpty( account.Username ) );
            Assert.IsFalse( String.IsNullOrEmpty( account.Name ), "Did you enter your name on the TMDb?" );
        }

        /// <summary>
        ///     A test for GetAccountListsAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountListsAsyncTest()
        {
            var actual = await Target.GetAccountListsAsync( AccountId, SessionId );
            CheckGenericResult( actual );

            var list = actual.Result;
            Assert.AreEqual( list.PageNumber, 1, "Do you have any movie lists?" );
            Assert.IsTrue( list.TotalPages >= 1 );
            Assert.IsTrue( list.TotalResults >= 1 );
            Assert.IsTrue( list.MovieLists.Any() );
        }

        /// <summary>
        ///     A test for SetFavoriteAsync
        /// </summary>
        [TestMethod]
        public async Task SetFavoriteAsyncAddTest()
        {
            var favoriteRequest = new TmdbFavoriteRequest
                {
                    AddToFavorite = true,
                    Id = 550
                };

            var actual = await Target.SetFavoriteAsync( AccountId, favoriteRequest, SessionId );
            CheckGenericResult( actual, false );

            var status = actual.Result;
            Assert.IsTrue( status.StatusCode == 12 || status.StatusCode == 1 );
            Assert.IsFalse( String.IsNullOrEmpty( status.StatusMessage ) );
        }

        /// <summary>
        ///     A test for SetFavoriteAsync
        /// </summary>
        [TestMethod]
        public async Task SetFavoriteAsyncRemoveTest()
        {
            var favoriteRequest = new TmdbFavoriteRequest
                {
                    AddToFavorite = false,
                    Id = 550
                };

            var actual = await Target.SetFavoriteAsync( AccountId, favoriteRequest, SessionId );
            CheckGenericResult( actual, false );

            var status = actual.Result;
            Assert.AreEqual( status.StatusCode, 13 );
            Assert.IsFalse( String.IsNullOrEmpty( status.StatusMessage ) );
        }

        /// <summary>
        ///     A test for SetWatchListAsync
        /// </summary>
        [TestMethod]
        public async Task SetWatchlistAsyncAddTest()
        {
            var watchListRequest = new TmdbWatchListRequest
                {
                    Id = 550,
                    AddToWatchList = true
                };

            var actual = await Target.SetWatchListAsync( AccountId, watchListRequest, SessionId );
            CheckGenericResult( actual, false );

            var status = actual.Result;
            Assert.IsTrue( status.StatusCode == 12 || status.StatusCode == 1 );
            Assert.IsFalse( String.IsNullOrEmpty( status.StatusMessage ) );
        }

        /// <summary>
        ///     A test for SetWatchListAsync
        /// </summary>
        [TestMethod]
        public async Task SetWatchlistAsyncRemoveTest()
        {
            var watchListRequest = new TmdbWatchListRequest
                {
                    Id = 550,
                    AddToWatchList = false
                };

            var actual = await Target.SetWatchListAsync( AccountId, watchListRequest, SessionId );
            CheckGenericResult( actual, false );

            var status = actual.Result;
            Assert.AreEqual( status.StatusCode, 13 );
            Assert.IsFalse( String.IsNullOrEmpty( status.StatusMessage ) );
        }

        /// <summary>
        ///     A test for GetAccountFavoriteMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountFavoriteMoviesAsyncTest()
        {
            var actual = await Target.GetAccountFavoriteMoviesAsync( AccountId, SessionId );
            CheckGenericResult( actual );

            var favorite = actual.Result;
            Assert.AreEqual( favorite.PageNumber, 1, "Do you have any favorite movie?" );
            Assert.IsTrue( favorite.TotalPages >= 1 );
            Assert.IsTrue( favorite.TotalResults >= 1 );
            Assert.IsTrue( favorite.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetAccountRatedMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountRatedMoviesAsyncTest()
        {
            var actual = await Target.GetAccountRatedMoviesAsync( AccountId, SessionId );
            CheckGenericResult( actual );

            var ratedMovies = actual.Result;
            Assert.AreEqual( ratedMovies.PageNumber, 1, "Did you have rated any movies?" );
            Assert.IsTrue( ratedMovies.TotalPages >= 1 );
            Assert.IsTrue( ratedMovies.TotalResults >= 1 );
            Assert.IsTrue( ratedMovies.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetAccountWatchListAsync
        /// </summary>
        [TestMethod]
        public async Task GetAccountWatchListAsyncTest()
        {
            var actual = await Target.GetAccountWatchListAsync( AccountId, SessionId );
            CheckGenericResult( actual );

            var watchList = actual.Result;
            Assert.AreEqual( watchList.PageNumber, 1, "Do you have any movies in your watch list??" );
            Assert.IsTrue( watchList.TotalPages >= 1 );
            Assert.IsTrue( watchList.TotalResults >= 1 );
            Assert.IsTrue( watchList.Movies.Any() );
        }

        #endregion Account

        #region Movie

        /// <summary>
        ///     A test for GetMovieAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieAsyncTest()
        {
            var actual = await Target.GetMovieAsync( 550 );
            CheckGenericResult( actual );

            var movie = actual.Result;
            Assert.AreEqual( 550, movie.Id );
        }

        /// <summary>
        ///     A test for GetAlternativeMovieTitlesAsync
        /// </summary>
        [TestMethod]
        public async Task GetAlternativeMovieTitlesAsyncTest()
        {
            var actual = await Target.GetAlternativeMovieTitlesAsync( 550 );
            CheckGenericResult( actual );

            var titles = actual.Result;
            Assert.AreEqual( 550, titles.Id );
            Assert.IsTrue( titles.Titles.Any(), "Does the movie have any alternative titles?" );
        }

        /// <summary>
        ///     A test for GetMovieCastAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieCastAsyncTest()
        {
            var actual = await Target.GetMovieCastAsync( 550 );
            CheckGenericResult( actual );

            var cast = actual.Result;
            Assert.AreEqual( 550, cast.Id );
            Assert.IsTrue( cast.Cast.Any(), "Does the movie has any cast members?" );
            Assert.IsTrue( cast.Crew.Any(), "Does the movie has any crew members?" );
        }

        /// <summary>
        ///     A test for GetMovieImagesAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieImagesAsyncTest()
        {
            var actual = await Target.GetMovieImagesAsync( 550 );
            CheckGenericResult( actual );

            var images = actual.Result;
            Assert.AreEqual( 550, images.Id );
            Assert.IsTrue( images.Backdrops.Any(), "Does the movie has any backdrops?" );
            Assert.IsTrue( images.Posters.Any(), "Does the movie has any posters?" );
        }

        /// <summary>
        ///     A test for GetMovieKeywordsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieKeywordsAsyncTest()
        {
            var actual = await Target.GetMovieKeywordsAsync( 550 );
            CheckGenericResult( actual );

            var keywords = actual.Result;
            Assert.AreEqual( 550, keywords.Id );
            Assert.IsTrue( keywords.Keywords.Any(), "Does the movie has any keywords?" );
        }

        /// <summary>
        ///     A test for GetMovieReleasesAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieReleasesAsyncTest()
        {
            var actual = await Target.GetMovieReleasesAsync( 550 );
            CheckGenericResult( actual );

            var releases = actual.Result;
            Assert.AreEqual( 550, releases.Id );
            Assert.IsTrue( releases.Releases.Any(), "Does the movie has any releases?" );
        }

        /// <summary>
        ///     A test for GetMovieTrailersAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieTrailersAsyncTest()
        {
            var actual = await Target.GetMovieTrailersAsync( 550 );
            CheckGenericResult( actual );

            var videos = actual.Result;
            Assert.AreEqual( 550, videos.Id );
            Assert.IsTrue( videos.Youtube.Any(), "Does the movie has any YouTube videos?" );
        }

        /// <summary>
        ///     A test for GetMovieTranslationsAsync
        /// </summary>
        [TestMethod]
        public async Task GetTranslationsAsyncTest()
        {
            var actual = await Target.GetMovieTranslationsAsync( 550 );
            CheckGenericResult( actual );

            var translations = actual.Result;
            Assert.AreEqual( 550, translations.Id );
            Assert.IsTrue( translations.Translations.Any(), "Does the movie has any translations?" );
        }

        /// <summary>
        ///     A test for GetSimilarMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetSimilarMoviesAsyncTest()
        {
            var actual = await Target.GetSimilarMoviesAsync( 550 );
            CheckGenericResult( actual );

            var similarMovies = actual.Result;
            Assert.AreEqual( similarMovies.PageNumber, 1, "Does the movie has any similar movies?" );
            Assert.IsTrue( similarMovies.TotalPages >= 1 );
            Assert.IsTrue( similarMovies.TotalResults >= 1 );
            Assert.IsTrue( similarMovies.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetMovieReviewsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieReviewsAsyncTest()
        {
            var actual = await Target.GetMovieReviewsAsync( 49026 );
            CheckGenericResult( actual );

            var reviews = actual.Result;
            Assert.AreEqual( reviews.PageNumber, 1, "Does the movie has any reviews?" );
            Assert.IsTrue( reviews.TotalPages >= 1 );
            Assert.IsTrue( reviews.TotalResults >= 1 );
            Assert.IsTrue( reviews.Reviews.Any() );
        }

        /// <summary>
        ///     A test for GetMovieListsAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieListsAsyncTest()
        {
            var actual = await Target.GetMovieListsAsync( 550 );
            CheckGenericResult( actual );

            var lists = actual.Result;
            Assert.AreEqual( lists.PageNumber, 1, "Is the movie part of any list?" );
            Assert.IsTrue( lists.TotalPages >= 1 );
            Assert.IsTrue( lists.TotalResults >= 1 );
            Assert.IsTrue( lists.MovieLists.Any() );
        }

        /// <summary>
        ///     A test for GetMovieChangesAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieChangesAsync()
        {
            var actual = await Target.GetMovieChangesAsync( 550 );
            CheckGenericResult( actual );

            var changes = actual.Result;
        }

        /// <summary>
        ///     A test for GetLatestMovieAsync
        /// </summary>
        [TestMethod]
        public async Task GetLatestMovieAsyncTest()
        {
            var actual = await Target.GetLatestMovieAsync();
            CheckGenericResult( actual );

            var latestMovie = actual.Result;
            Assert.IsTrue( latestMovie.Id > 0 );
        }

        /// <summary>
        ///     A test for GetUpcomingMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetUpcomingMoviesAsyncTest()
        {
            var actual = await Target.GetUpcomingMoviesAsync();
            CheckGenericResult( actual );

            var upcoming = actual.Result;
            Assert.AreEqual( upcoming.PageNumber, 1 );
            Assert.IsTrue( upcoming.TotalPages >= 1 );
            Assert.IsTrue( upcoming.TotalResults >= 1 );
            Assert.IsTrue( upcoming.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetNowPlayingmoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetNowPlayingmoviesAsyncTest()
        {
            var actual = await Target.GetNowPlayingmoviesAsync();
            CheckGenericResult( actual );

            var nowPlaying = actual.Result;
            Assert.AreEqual( nowPlaying.PageNumber, 1 );
            Assert.IsTrue( nowPlaying.TotalPages >= 1 );
            Assert.IsTrue( nowPlaying.TotalResults >= 1 );
            Assert.IsTrue( nowPlaying.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetPopularMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetPopularMoviesAsyncTest()
        {
            var actual = await Target.GetPopularMoviesAsync();
            CheckGenericResult( actual );

            var popular = actual.Result;
            Assert.AreEqual( popular.PageNumber, 1 );
            Assert.IsTrue( popular.TotalPages >= 1 );
            Assert.IsTrue( popular.TotalResults >= 1 );
            Assert.IsTrue( popular.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetTopRatedMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetTopRatedMoviesAsyncTest()
        {
            var actual = await Target.GetTopRatedMoviesAsync();
            CheckGenericResult( actual );

            var topRated = actual.Result;
            Assert.AreEqual( topRated.PageNumber, 1 );
            Assert.IsTrue( topRated.TotalPages >= 1 );
            Assert.IsTrue( topRated.TotalResults >= 1 );
            Assert.IsTrue( topRated.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetMovieAccountStateAsync
        /// </summary>
        [TestMethod]
        public async Task GetMovieAccountStateAsyncTest()
        {
            var actual = await Target.GetMovieAccountStateAsync( 550, SessionId );
            CheckGenericResult( actual );

            var state = actual.Result;
            Assert.AreEqual( 550, state.Id );
            if ( state.RatedByUser )
                Assert.IsTrue( state.RatingRequest.Value > 0 );
            else
                Assert.IsNull( state.RatingRequest );
        }

        /// <summary>
        ///     A test for RateMovieAsync
        /// </summary>
        [TestMethod]
        public async Task RateMovieAsyncTest()
        {
            var rating = await Target.RateMovieAsync( 550, new TmdbMovieRatingRequest
                {
                    Value = 9.1
                }, SessionId );
            Assert.IsNull( rating.Result );
            Assert.IsFalse( String.IsNullOrEmpty( rating.ApiErrorResponse.StatusMessage ) );
        }

        /// <summary>
        ///     A test for RateMovieAsync
        /// </summary>
        [TestMethod]
        public async Task RateMovieAsyncTest1()
        {
            var ratingRequest = new TmdbMovieRatingRequest
                {
                    Value = 9
                };
            var guestSession = await Target.GetGuestSessionAsync();
            Assert.IsTrue( guestSession.Result.Success, "GetGuestSessionAsync failed!" );

            var actual = await Target.RateMovieAsync( 550, ratingRequest, guestSessionId: guestSession.Result.GuestSessionId );
            CheckGenericResult( actual, false );

            var state = actual.Result;
            Assert.IsTrue( state.StatusCode == 1 || state.StatusCode == 12 );
            Assert.IsFalse( String.IsNullOrEmpty( state.StatusMessage ) );
        }

        #endregion Movie

        #region Collection

        /// <summary>
        ///     A test for GetCollectionAsync
        /// </summary>
        [TestMethod]
        public async Task GetCollectionAsyncTest()
        {
            var actual = await Target.GetCollectionAsync( 119 );
            CheckGenericResult( actual );

            var collection = actual.Result;
            Assert.IsFalse( String.IsNullOrEmpty( collection.BackdropPath ) );
            Assert.IsFalse( String.IsNullOrEmpty( collection.PosterPath ) );
            Assert.IsFalse( String.IsNullOrEmpty( collection.Name ) );
            Assert.AreEqual( 119, collection.Id );
            Assert.IsTrue( collection.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetCollectionImagesAsync
        /// </summary>
        [TestMethod]
        public async Task GetCollectionImagesAsyncTest()
        {
            var actual = await Target.GetCollectionImagesAsync( 119 );
            CheckGenericResult( actual );

            var iamges = actual.Result;
            Assert.IsTrue( iamges.Backdrops.Any() );
        }

        #endregion Collection

        #region People

        /// <summary>
        ///     A test for GetPersonAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonAsyncTest()
        {
            var actual = await Target.GetPersonAsync( 287 );
            CheckGenericResult( actual );

            var person = actual.Result;
            Assert.AreEqual( 287, person.Id );
            Assert.IsFalse( String.IsNullOrEmpty( person.Name ) );
        }

        /// <summary>
        ///     A test for GetPersonCreditsAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonCreditsAsyncTest()
        {
            var actual = await Target.GetPersonCreditsAsync( 287 );
            CheckGenericResult( actual );

            var credits = actual.Result;
            Assert.AreEqual( 287, credits.Id );
            Assert.IsTrue( credits.Cast.Any() );
            Assert.IsTrue( credits.Crew.Any() );
        }

        /// <summary>
        ///     A test for GetPersonImageAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonImageAsyncTest()
        {
            var actual = await Target.GetPersonImageAsync( 287 );
            CheckGenericResult( actual );

            var iamges = actual.Result;
            Assert.AreEqual( 287, iamges.Id );
            Assert.IsTrue( iamges.Images.Any() );
        }

        /// <summary>
        ///     A test for GetPersonChangesAsync
        /// </summary>
        [TestMethod]
        public async Task GetPersonChangesAsyncTest()
        {
            var actual = await Target.GetPersonChangesAsync( 287 );
            CheckGenericResult( actual );
        }

        /// <summary>
        ///     A test for GetPopularPeopleAsync
        /// </summary>
        [TestMethod]
        public async Task GetPopularPersonsAsyncTest()
        {
            var actual = await Target.GetPopularPeopleAsync();
            CheckGenericResult( actual );

            var people = actual.Result;
            Assert.AreEqual( 1, people.PageNumber );
            Assert.IsTrue( people.TotalPages > 0 );
            Assert.IsTrue( people.TotalResults > 0 );
            Assert.IsTrue( people.People.Any() );
        }

        /// <summary>
        ///     A test for GetPopularPeopleAsync
        /// </summary>
        [TestMethod]
        public async Task GetLatestPersonAsyncTest()
        {
            var actual = await Target.GetLatestPersonAsync();
            CheckGenericResult( actual );

            var latestPerson = actual.Result;
            Assert.IsTrue( latestPerson.Id > 0 );
        }

        #endregion People

        #region Lists

        /// <summary>
        ///     A test for GetListAsync
        /// </summary>
        [TestMethod]
        public async Task GetListAsyncTest()
        {
            var actual = await Target.GetListAsync( "509ec17b19c2950a0600050d" );
            CheckGenericResult( actual );

            var list = actual.Result;
            Assert.AreEqual( "509ec17b19c2950a0600050d", list.Id );
            Assert.IsTrue( list.Movies.Any() );
        }

        /// <summary>
        ///     A test for GetListStateAsync
        /// </summary>
        [TestMethod]
        public async Task GetListStateAsyncTest()
        {
            var actual = await Target.GetListStateAsync( "509ec17b19c2950a0600050d", 74643 );
            CheckGenericResult( actual );

            var list = actual.Result;
            Assert.AreEqual( "509ec17b19c2950a0600050d", list.Id );
            Assert.IsTrue( list.IsItemPresent );
        }

        /// <summary>
        ///     A test for AddItemToListAsync
        /// </summary>
        [TestMethod]
        public async Task AddItemToListAsyncTest()
        {
            var item = new TmdbListItemRequest
                {
                    MovieId = 550,
                };

            var actual = await Target.AddItemToListAsync( "51c991a719c29575b200e5e0", item, SessionId );

            if ( actual.Error == null )
            {
                var state = actual.Result;
                Assert.IsTrue( state.StatusCode == 1 || state.StatusCode == 12 );
                Assert.IsFalse( String.IsNullOrEmpty( state.StatusMessage ) );
            }
            else
            {
                Assert.IsTrue( actual.Error.Message.Contains( "403" ) );
                Assert.AreEqual( 8, actual.ApiErrorResponse.StatusCode );
            }
        }

        /// <summary>
        ///     A test for CreateMovieListAsync
        /// </summary>
        [TestMethod]
        public async Task CreateMovieListAsyncTest()
        {
            var item = new TmdbListItemRequest
                {
                    MovieId = 550,
                };

            var actual = await Target.CreateMovieListAsync( SessionId, new TmdbCreateMovieListRequest
                {
                    Name = "A name" + Guid.NewGuid().ToString().Substring( 0, 10 ),
                    Description = Guid.NewGuid().ToString(),
                    Language = "EN"
                } );
            CheckGenericResult( actual, false );

            var state = actual.Result;
            Assert.IsTrue( state.StatusCode == 1 || state.StatusCode == 12 );
            Assert.IsFalse( String.IsNullOrEmpty( state.StatusMessage ) );
            Assert.IsFalse( String.IsNullOrEmpty( state.ListId ) );
        }

        /// <summary>
        ///     A test for RemoveItemFromListAsync
        /// </summary>
        [TestMethod]
        public async Task RemoveItemFromListAsyncTest()
        {
            var item = new TmdbListItemRequest
                {
                    MovieId = 72190,
                };

            var actual = await Target.RemoveItemFromListAsync( "51c991a719c29575b200e5e0", item, SessionId );
            CheckGenericResult( actual, false );

            var state = actual.Result;
            Assert.AreEqual( 21, state.StatusCode, "Item shouldn't be in the list." );
            Assert.IsFalse( String.IsNullOrEmpty( state.StatusMessage ) );
        }

        /// <summary>
        ///     A test for DeleteListAsync
        /// </summary>
        [TestMethod]
        public async Task DeleteListAsyncTest()
        {
            var actual = await Target.DeleteListAsync( "51cd3927760ee3571f0e3297", SessionId );
        }

        #endregion Lists

        #region Companies

        /// <summary>
        ///     A test for GetCompanyAsync
        /// </summary>
        [TestMethod]
        public async Task GetCompanyAsyncTest()
        {
            var actual = await Target.GetCompanyAsync( 1 );
            CheckGenericResult( actual );

            var company = actual.Result;
            Assert.AreEqual( 1, company.Id );
            Assert.IsFalse( String.IsNullOrEmpty( company.Name ) );
        }

        /// <summary>
        ///     A test for GetCompanyMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetCompanyMoviesAsyncTest()
        {
            var actual = await Target.GetCompanyMoviesAsync( 1 );
            CheckGenericResult( actual );

            var movies = actual.Result;
            Assert.AreEqual( 1, movies.PageNumber );
            Assert.IsTrue( movies.TotalPages > 0 );
            Assert.IsTrue( movies.TotalResults > 0 );
            Assert.IsTrue( movies.Movies.Any() );
        }

        #endregion Companies

        #region Genres

        /// <summary>
        ///     A test for GetGenresAsync
        /// </summary>
        [TestMethod]
        public async Task GetGenresAsyncTest()
        {
            var actual = await Target.GetGenresAsync();
            CheckGenericResult( actual );

            var genres = actual.Result;
            Assert.IsTrue( genres.Genres.Any() );
        }

        /// <summary>
        ///     A test for GetGenreMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetGenreMoviesAsyncTest()
        {
            var actual = await Target.GetGenreMoviesAsync( 28 );
            CheckGenericResult( actual );

            var movies = actual.Result;
            Assert.AreEqual( 1, movies.PageNumber );
            Assert.IsTrue( movies.TotalPages > 0 );
            Assert.IsTrue( movies.TotalResults > 0 );
            Assert.IsTrue( movies.Movies.Any() );
        }

        #endregion Genres

        #region Keywords

        /// <summary>
        ///     A test for GetKeywordAsync
        /// </summary>
        [TestMethod]
        public async Task GetKeywordAsyncTest()
        {
            var actual = await Target.GetKeywordAsync( 1721 );
            CheckGenericResult( actual );

            var keyword = actual.Result;
            Assert.AreEqual( 1721, keyword.Id );
            Assert.IsFalse( String.IsNullOrEmpty( keyword.Name ) );
        }

        /// <summary>
        ///     A test for GetKeywordMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetKeywordMoviesAsyncTest()
        {
            var actual = await Target.GetKeywordMoviesAsync( 1721 );
            CheckGenericResult( actual );

            var movies = actual.Result;
            Assert.AreEqual( 1, movies.PageNumber );
            Assert.IsTrue( movies.TotalPages > 0 );
            Assert.IsTrue( movies.TotalResults > 0 );
            Assert.IsTrue( movies.Movies.Any() );
        }

        #endregion Keywords

        #region Discover

        /// <summary>
        ///     A test for DiscoverMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task DiscoverMoviesAsyncTest()
        {
            var actual = await Target.DiscoverMoviesAsync();
            CheckGenericResult( actual );

            var movies = actual.Result;
            Assert.AreEqual( 1, movies.PageNumber );
            Assert.IsTrue( movies.TotalPages > 0 );
            Assert.IsTrue( movies.TotalResults > 0 );
            Assert.IsTrue( movies.Movies.Any() );
        }

        #endregion Discover

        #region Search

        /// <summary>
        ///     A test for SearchMovieAsync
        /// </summary>
        [TestMethod]
        public async Task SearchMovieAsyncTest()
        {
            var actual = await Target.SearchMovieAsync( "The lord of the rings" );
            CheckGenericResult( actual );

            var movies = actual.Result;
            Assert.AreEqual( 1, movies.PageNumber );
            Assert.IsTrue( movies.TotalPages > 0 );
            Assert.IsTrue( movies.TotalResults > 0 );
            Assert.IsTrue( movies.Movies.Any() );
        }

        /// <summary>
        ///     A test for SearchMovieCollectionAsync
        /// </summary>
        [TestMethod]
        public async Task SearchMovieCollectionAsyncTest()
        {
            var actual = await Target.SearchMovieCollectionAsync( "The lord of the rings" );
            CheckGenericResult( actual );

            var collections = actual.Result;
            Assert.AreEqual( 1, collections.PageNumber );
            Assert.IsTrue( collections.TotalPages > 0 );
            Assert.IsTrue( collections.TotalResults > 0 );
            Assert.IsTrue( collections.MovieCollections.Any() );
        }

        /// <summary>
        ///     A test for SearchPersonAsync
        /// </summary>
        [TestMethod]
        public async Task SearchPersonAsyncTest()
        {
            var actual = await Target.SearchPersonAsync( "Stone" );
            CheckGenericResult( actual );

            var people = actual.Result;
            Assert.AreEqual( 1, people.PageNumber );
            Assert.IsTrue( people.TotalPages > 0 );
            Assert.IsTrue( people.TotalResults > 0 );
            Assert.IsTrue( people.People.Any() );
        }

        /// <summary>
        ///     A test for SearchListAsync
        /// </summary>
        [TestMethod]
        public async Task SearchListAsyncTest()
        {
            var actual = await Target.SearchListAsync( "Oscars" );
            CheckGenericResult( actual );

            var lists = actual.Result;
            Assert.AreEqual( 1, lists.PageNumber );
            Assert.IsTrue( lists.TotalPages > 0 );
            Assert.IsTrue( lists.TotalResults > 0 );
            Assert.IsTrue( lists.MovieLists.Any() );
        }

        /// <summary>
        ///     A test for SearchCompanyAsync
        /// </summary>
        [TestMethod]
        public async Task SearchCompanyAsyncTest()
        {
            var actual = await Target.SearchCompanyAsync( "Pictures" );
            CheckGenericResult( actual );

            var companies = actual.Result;
            Assert.AreEqual( 1, companies.PageNumber );
            Assert.IsTrue( companies.TotalPages > 0 );
            Assert.IsTrue( companies.TotalResults > 0 );
            Assert.IsTrue( companies.Companies.Any() );
        }

        /// <summary>
        ///     A test for SearchKeywordAsync
        /// </summary>
        [TestMethod]
        public async Task SearchKeywordAsyncTest()
        {
            var actual = await Target.SearchKeywordAsync( "Action" );
            CheckGenericResult( actual );

            var keywords = actual.Result;
            Assert.AreEqual( 1, keywords.PageNumber );
            Assert.IsTrue( keywords.TotalPages > 0 );
            Assert.IsTrue( keywords.TotalResults > 0 );
            Assert.IsTrue( keywords.Keywords.Any() );
        }

        #endregion Search

        #region Review

        /// <summary>
        ///     A test for GetReviewAsync
        /// </summary>
        [TestMethod]
        public async Task GetReviewAsyncTest()
        {
            var actual = await Target.GetReviewAsync( "5013bc76760ee372cb00253e" );
            CheckGenericResult( actual );

            var review = actual.Result;
            Assert.AreEqual( "5013bc76760ee372cb00253e", review.Id );
            Assert.IsFalse( String.IsNullOrEmpty( review.Content ) );
            Assert.IsFalse( String.IsNullOrEmpty( review.Author ) );
        }

        #endregion Review

        #region Changes

        /// <summary>
        ///     A test for GetChangedMoviesAsync
        /// </summary>
        [TestMethod]
        public async Task GetChangedMoviesAsyncTest()
        {
            var actual = await Target.GetChangedMoviesAsync();
            CheckGenericResult( actual );

            var keywords = actual.Result;
            Assert.AreEqual( 1, keywords.PageNumber );
            Assert.IsTrue( keywords.TotalPages > 0 );
            Assert.IsTrue( keywords.TotalResults > 0 );
            Assert.IsTrue( keywords.ChangedEntries.Any() );
        }

        /// <summary>
        ///     A test for GetChangedPeopleAsync
        /// </summary>
        [TestMethod]
        public async Task GetChangedPeopleAsyncTest()
        {
            var actual = await Target.GetChangedPeopleAsync();
            CheckGenericResult( actual );

            var keywords = actual.Result;
            Assert.AreEqual( 1, keywords.PageNumber );
            Assert.IsTrue( keywords.TotalPages > 0 );
            Assert.IsTrue( keywords.TotalResults > 0 );
            Assert.IsTrue( keywords.ChangedEntries.Any() );
        }

        #endregion Changes

        #region Jobs

        /// <summary>
        ///     A test for GetJobsAsync
        /// </summary>
        [TestMethod]
        public async Task GetJobsAsyncTest()
        {
            var actual = await Target.GetJobsAsync();
            CheckGenericResult( actual );

            var jobs = actual.Result;
            Assert.IsTrue( jobs.Departments.Any() );
            Assert.IsTrue( jobs.Departments.Any( x => x.JobList.Any() ) );
        }

        #endregion Jobs

        #region Images
        /// <summary>
        ///     A Test for DownloadImageAsync
        /// </summary>
        public async Task DownloadImageAsyncTest()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync( 550 );

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;
            var size = tmdbConfiguration.Result.ImageConfiguration.PosterSizes.Last();
            var fileName = Guid.NewGuid().ToString() + ".jpg";

            if ( File.Exists( fileName ) )
                File.Delete( fileName );

            var actual = await Target.DownloadImageAsync( filePath, tmdbConfiguration.Result, fileName, size );
            Assert.IsTrue( File.Exists( fileName ) );
            Assert.AreEqual( filePath, actual.Result );
        }

        /// <summary>
        ///     A Test for DownloadImageAsync
        /// </summary>
        public async Task DownloadImageAsyncTest1()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;
            var fileName = Guid.NewGuid().ToString() + ".jpg";

            if (File.Exists(fileName))
                File.Delete(fileName);

            var actual = await Target.DownloadImageAsync(filePath, tmdbConfiguration.Result, fileName);
            Assert.IsTrue(File.Exists(fileName));
            Assert.AreEqual(filePath, actual.Result);
        }

        /// <summary>
        ///     A Test for GetImageAsync
        /// </summary>
        public async Task GetImageAsyncTest()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;
            var size = tmdbConfiguration.Result.ImageConfiguration.PosterSizes.First();

            var actual = await Target.GetImageAsync( filePath, tmdbConfiguration.Result, size );
            Assert.IsTrue( actual.Result.Length > 0 );
        }

        /// <summary>
        ///     A Test for GetImageAsync
        /// </summary>
        public async Task GetImageAsyncTest1()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;

            var actual = await Target.GetImageAsync(filePath, tmdbConfiguration.Result);
            Assert.IsTrue(actual.Result.Length > 0);
        }

        /// <summary>
        ///     A Test for GetImageUrl
        /// </summary>
        public async Task GetImageUrlTest()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;
            var size = tmdbConfiguration.Result.ImageConfiguration.PosterSizes.First();

            Target.ApiConfiguration.UseSecureConnection = false;
            var actual = Target.GetImageUrl( filePath, tmdbConfiguration.Result, size );
            Assert.AreEqual( String.Format( "{0}/{1}/{2}", tmdbConfiguration.Result.ImageConfiguration.BaseUrl, size, filePath ), actual );
        }

        /// <summary>
        ///     A Test for GetImageUrl
        /// </summary>
        public async Task GetImageUrlTest1()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;

            Target.ApiConfiguration.UseSecureConnection = false;
            var actual = Target.GetImageUrl(filePath, tmdbConfiguration.Result);
            Assert.AreEqual(String.Format("{0}/{1}/{2}", tmdbConfiguration.Result.ImageConfiguration.BaseUrl, Target.ApiConfiguration.OriginalImageSizeValue, filePath), actual);
        }

        /// <summary>
        ///     A Test for GetImageUrl
        /// </summary>
        public async Task GetImageUrlTest2()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;
            var size = tmdbConfiguration.Result.ImageConfiguration.PosterSizes.First();

            Target.ApiConfiguration.UseSecureConnection = true;
            var actual = Target.GetImageUrl(filePath, tmdbConfiguration.Result, size);
            Assert.AreEqual(String.Format("{0}/{1}/{2}", tmdbConfiguration.Result.ImageConfiguration.SecureBaseUrl, size, filePath), actual);
        }

        /// <summary>
        ///     A Test for GetImageUrl
        /// </summary>
        public async Task GetImageUrlTest3()
        {
            var tmdbConfiguration = await Target.GetConfigurationAsync();
            var movie = await Target.GetMovieAsync(550);

            Assert.IsNotNull(tmdbConfiguration.Result, "GetConfigurationAsync failed.");
            Assert.IsNotNull(movie.Result, "GetMovieAsync failed.");

            var filePath = movie.Result.PosterPath;

            Target.ApiConfiguration.UseSecureConnection = true;
            var actual = Target.GetImageUrl(filePath, tmdbConfiguration.Result);
            Assert.AreEqual(String.Format("{0}/{1}/{2}", tmdbConfiguration.Result.ImageConfiguration.SecureBaseUrl, Target.ApiConfiguration.OriginalImageSizeValue, filePath), actual);
        }
        #endregion

        #region Properties

        /// <summary>
        ///     A test for ApiClient
        /// </summary>
        [TestMethod]
        public void ApiClientTest()
        {
            var target = new ApiWrapper();
            var expected = new ApiClientNet();
            target.ApiClient = expected;
            var actual = target.ApiClient;
            Assert.AreSame( expected, actual );
        }

        /// <summary>
        ///     A test for ApiConfiguration
        /// </summary>
        [TestMethod]
        public void ApiConfigurationTest()
        {
            var target = new ApiWrapper();
            var expected = new ApiConfiguration();
            target.ApiConfiguration = expected;
            var actual = target.ApiConfiguration;
            Assert.AreSame( expected, actual );
        }

        #endregion Properties
    }
}
